
package com.trydofor.id.doer.shell;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;

import com.trydofor.aloe.exception.Exceptions;

/**
 * the help of Command's argument
 * 
 * @author : Shi Rongjiu (www.trydofor.com)
 */
public class ArgHelp {
    
    private final String name;
    private boolean      required;
    private boolean      editable;
    private String       manual;
    private String       pattern;
    private String       defaolt;
    private List<String> options;
    //
    private Pattern      regexp;
    
    /**
     * the help of argument
     * 
     * @param name the name
     * @throws NullPointerException if name is null
     */
    public ArgHelp(String name) {
        Exceptions.checkNullPointer(name);
        this.name = name;
        this.required = false;
        this.editable = true;
        this.options = new ArrayList<String>();
    }
    
    /**
     * @return the manual
     */
    public String getManual() {
        return manual;
    }
    
    /**
     * @param manual the manual to set
     */
    public void setManual(String manual) {
        this.manual = manual;
    }
    
    /**
     * @return the pattern
     */
    public String getPattern() {
        return pattern;
    }
    
    /**
     * @param pattern the pattern to set
     */
    public void setPattern(String pattern) {
        this.pattern = pattern;
        if (pattern != null) {
            this.regexp = Pattern.compile(pattern);
        }
    }
    
    /**
     * @return the default
     */
    public String getDefault() {
        return defaolt;
    }
    
    /**
     * @param defaolt the default to set
     */
    public void setDefault(String defaolt) {
        this.defaolt = defaolt;
    }
    
    /**
     * @return the options
     */
    public List<String> getOptions() {
        return options;
    }
    
    /**
     * @param option the option to add
     * @param options the others options to add
     */
    public void addOption(String option, String... options) {
        this.options.add(option);
        for (String string : options) {
            this.options.add(string);
        }
    }
    
    /**
     * @return the name
     */
    public String getName() {
        return name;
    }
    
    /**
     * @return the required
     */
    public boolean isRequired() {
        return required;
    }
    
    /**
     * @param required the required to set
     */
    public void setRequired(boolean required) {
        this.required = required;
    }
    
    /**
     * @return the editable
     */
    public boolean isEditable() {
        return editable;
    }
    
    /**
     * @param editable the editable to set
     */
    public void setEditable(boolean editable) {
        this.editable = editable;
    }
    
    /**
     * validate the data with required and pattern/options
     * 
     * @param data the data
     * @return null if valid, otherwise error message
     */
    public String validate(String data) {
        if (required && (data == null || data.length() == 0)) return "required but empty";
        // pattern
        if (regexp != null && !regexp.matcher(data).find()) {
            return "NOT matches the pattern=" + pattern + ", data=" + data;
        }
        // options
        if (!editable && options.size() > 0) {
            boolean good = false;
            for (String opt : options) {
                if (opt.equals(data)) {
                    good = true;
                    break;
                }
            }
            if (!good) {
                return "NOT in the options" + ", data=" + data;
            }
        }
        
        return null;
    }
    
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(" - ");
        sb.append(name);
        sb.append("\t");
        sb.append(required);
        sb.append("\t");
        sb.append(editable);
        sb.append("\t");
        sb.append(manual);
        if (pattern != null) {
            sb.append("\t/");
            sb.append(pattern);
            sb.append("/");
        }
        if (defaolt != null) {
            sb.append("\t");
            sb.append(defaolt);
        }
        if (options.size() > 0) {
            sb.append("\t");
            sb.append(Arrays.toString(options.toArray()));
        }
        return sb.toString();
    }
}
